home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / DirectInput / Keyboard / keyboard.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-31  |  23.5 KB  |  619 lines

  1. //-----------------------------------------------------------------------------
  2. // File: keyboard.cpp
  3. //
  4. // Desc: The Keyboard sample show how to use a DirectInput keyboard device 
  5. //       and the differences between cooperative levels and data styles. 
  6. //
  7. // Copyright (c) 1999-2001 Microsoft Corporation. All rights reserved.
  8. //-----------------------------------------------------------------------------
  9. #define STRICT
  10. #include <tchar.h>
  11. #include <windows.h>
  12. #include <basetsd.h>
  13. #include <dinput.h>
  14. #include "resource.h"
  15.  
  16.  
  17. //-----------------------------------------------------------------------------
  18. // Function-prototypes
  19. //-----------------------------------------------------------------------------
  20. INT_PTR CALLBACK MainDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam );
  21. HRESULT OnInitDialog( HWND hDlg );
  22. VOID    UpdateUI( HWND hDlg );
  23. HRESULT OnCreateDevice( HWND hDlg );
  24. HRESULT ReadImmediateData( HWND hDlg );
  25. HRESULT ReadBufferedData( HWND hDlg );
  26. VOID    FreeDirectInput();
  27.  
  28.  
  29.  
  30.  
  31. //-----------------------------------------------------------------------------
  32. // Defines, constants, and global variables
  33. //-----------------------------------------------------------------------------
  34. #define SAFE_DELETE(p)  { if(p) { delete (p);     (p)=NULL; } }
  35. #define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
  36.  
  37. #define SAMPLE_BUFFER_SIZE 8  // arbitrary number of buffer elements
  38.  
  39. LPDIRECTINPUT8       g_pDI       = NULL;         
  40. LPDIRECTINPUTDEVICE8 g_pKeyboard = NULL;     
  41.  
  42.  
  43.  
  44.  
  45. //-----------------------------------------------------------------------------
  46. // Name: WinMain()
  47. // Desc: Entry point for the application.  Since we use a simple dialog for 
  48. //       user interaction we don't need to pump messages.
  49. //-----------------------------------------------------------------------------
  50. int WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, int )
  51. {
  52.     // Display the main dialog box.
  53.     DialogBox( hInst, MAKEINTRESOURCE(IDD_KEYBOARD), NULL, MainDlgProc );
  54.     
  55.     return TRUE;
  56. }
  57.  
  58.  
  59.  
  60.  
  61.  
  62. //-----------------------------------------------------------------------------
  63. // Name: MainDlgProc()
  64. // Desc: Handles dialog messages
  65. //-----------------------------------------------------------------------------
  66. INT_PTR CALLBACK MainDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
  67. {
  68.     switch( msg ) 
  69.     {
  70.         case WM_INITDIALOG:
  71.             OnInitDialog( hDlg );
  72.             break;
  73.         
  74.         case WM_COMMAND:
  75.             switch( LOWORD(wParam) )
  76.             {
  77.                 case IDCANCEL:
  78.                     EndDialog( hDlg, 0 ); 
  79.                     break;
  80.  
  81.                 case IDC_EXCLUSIVE:
  82.                 case IDC_NONEXCLUSIVE:
  83.                 case IDC_FOREGROUND:
  84.                 case IDC_BACKGROUND:
  85.                 case IDC_IMMEDIATE:
  86.                 case IDC_BUFFERED:
  87.                 case IDC_WINDOWSKEY:
  88.                     UpdateUI( hDlg );
  89.                     break;
  90.  
  91.                 case IDC_CREATEDEVICE:
  92.                     if( NULL == g_pKeyboard )
  93.                     {
  94.                         if( FAILED( OnCreateDevice( hDlg ) ) )
  95.                         {
  96.                             MessageBox( hDlg, _T("CreateDevice() failed. ")
  97.                                               _T("The sample will now exit."), 
  98.                                               _T("Keyboard"), MB_ICONERROR | MB_OK );
  99.                             FreeDirectInput();
  100.                         }
  101.                     }
  102.                     else
  103.                     {
  104.                         FreeDirectInput();
  105.                     }
  106.  
  107.                     UpdateUI( hDlg );
  108.                     break;
  109.  
  110.                 default:
  111.                     return FALSE; // Message not handled 
  112.             }       
  113.             break;
  114.  
  115.         case WM_ACTIVATE:
  116.             if( WA_INACTIVE != wParam && g_pKeyboard )
  117.             {
  118.                 // Make sure the device is acquired, if we are gaining focus.
  119.                 g_pKeyboard->Acquire();
  120.             }
  121.             break;
  122.         
  123.         case WM_TIMER:
  124.             // Update the input device every timer message
  125.             {
  126.                 BOOL bImmediate = ( IsDlgButtonChecked( hDlg, IDC_IMMEDIATE  ) == BST_CHECKED );
  127.  
  128.                 if( bImmediate )
  129.                 {
  130.                     if( FAILED( ReadImmediateData( hDlg ) ) )
  131.                     {
  132.                         KillTimer( hDlg, 0 );    
  133.                         MessageBox( NULL, _T("Error reading input state. ")
  134.                                           _T("The sample will now exit."), 
  135.                                           _T("Keyboard"), MB_ICONERROR | MB_OK );
  136.                         EndDialog( hDlg, TRUE ); 
  137.                     }
  138.                 }
  139.                 else
  140.                 {
  141.                     if( FAILED( ReadBufferedData( hDlg ) ) )
  142.                     {
  143.                         KillTimer( hDlg, 0 );    
  144.                         MessageBox( NULL, _T("Error reading input state. ")
  145.                                           _T("The sample will now exit."), 
  146.                                           _T("Keyboard"), MB_ICONERROR | MB_OK );
  147.                         EndDialog( hDlg, TRUE ); 
  148.                     }
  149.                 }
  150.             }
  151.             break;
  152.         
  153.         case WM_DESTROY:
  154.             // Cleanup everything
  155.             KillTimer( hDlg, 0 );    
  156.             FreeDirectInput();    
  157.             break;
  158.  
  159.         default:
  160.             return FALSE; // Message not handled 
  161.     }
  162.  
  163.     return TRUE; // Message handled 
  164. }
  165.  
  166.  
  167.  
  168.  
  169. //-----------------------------------------------------------------------------
  170. // Name: OnInitDialog()
  171. // Desc: Initialize the DirectInput variables.
  172. //-----------------------------------------------------------------------------
  173. HRESULT OnInitDialog( HWND hDlg )
  174. {
  175.     // Load the icon
  176.     HICON hIcon = LoadIcon( GetModuleHandle(NULL), MAKEINTRESOURCE( IDI_MAIN ) );
  177.  
  178.     // Set the icon for this dialog.
  179.     PostMessage( hDlg, WM_SETICON, ICON_BIG,   (LPARAM) hIcon );  // Set big icon
  180.     PostMessage( hDlg, WM_SETICON, ICON_SMALL, (LPARAM) hIcon );  // Set small icon
  181.  
  182.     // Check the 'exclusive', 'foreground', and 'immediate' buttons by default. 
  183.     CheckRadioButton( hDlg, IDC_EXCLUSIVE,  IDC_NONEXCLUSIVE, IDC_EXCLUSIVE );
  184.     CheckRadioButton( hDlg, IDC_FOREGROUND, IDC_BACKGROUND,   IDC_FOREGROUND );
  185.     CheckRadioButton( hDlg, IDC_IMMEDIATE,  IDC_BUFFERED,     IDC_IMMEDIATE );
  186.  
  187.     UpdateUI( hDlg );
  188.  
  189.     return S_OK;
  190. }
  191.  
  192.  
  193.  
  194.  
  195. //-----------------------------------------------------------------------------
  196. // Name: UpdateUI()
  197. // Desc: Enables/disables the UI, and sets the dialog behavior text based on the UI
  198. //-----------------------------------------------------------------------------
  199. VOID UpdateUI( HWND hDlg )
  200. {
  201.     TCHAR   strExcepted[2048];
  202.     BOOL    bExclusive;
  203.     BOOL    bForeground;
  204.     BOOL    bImmediate;
  205.     BOOL    bDisableWindowsKey;
  206.  
  207.     // Detrimine where the buffer would like to be allocated 
  208.     bExclusive         = ( IsDlgButtonChecked( hDlg, IDC_EXCLUSIVE  ) == BST_CHECKED );
  209.     bForeground        = ( IsDlgButtonChecked( hDlg, IDC_FOREGROUND ) == BST_CHECKED );
  210.     bImmediate         = ( IsDlgButtonChecked( hDlg, IDC_IMMEDIATE  ) == BST_CHECKED );
  211.     bDisableWindowsKey = ( IsDlgButtonChecked( hDlg, IDC_WINDOWSKEY ) == BST_CHECKED );
  212.  
  213.     if( g_pKeyboard )
  214.     {
  215.         SetDlgItemText( hDlg, IDC_CREATEDEVICE, TEXT("Release Device") );
  216.         SetDlgItemText( hDlg, IDC_DATA, TEXT("") );
  217.  
  218.         EnableWindow( GetDlgItem( hDlg, IDC_EXCLUSIVE    ), FALSE );
  219.         EnableWindow( GetDlgItem( hDlg, IDC_NONEXCLUSIVE ), FALSE );
  220.         EnableWindow( GetDlgItem( hDlg, IDC_FOREGROUND   ), FALSE );
  221.         EnableWindow( GetDlgItem( hDlg, IDC_BACKGROUND   ), FALSE );
  222.         EnableWindow( GetDlgItem( hDlg, IDC_IMMEDIATE    ), FALSE );
  223.         EnableWindow( GetDlgItem( hDlg, IDC_BUFFERED     ), FALSE );
  224.         EnableWindow( GetDlgItem( hDlg, IDC_WINDOWSKEY   ), FALSE );
  225.     }
  226.     else
  227.     {
  228.         SetDlgItemText( hDlg, IDC_CREATEDEVICE, TEXT("&Create Device") );
  229.         SetDlgItemText( hDlg, IDC_DATA, 
  230.                         TEXT("Device not created. Choose settings and click 'Create Device' then type to see results") );   
  231.  
  232.         EnableWindow( GetDlgItem( hDlg, IDC_EXCLUSIVE    ), TRUE );
  233.         EnableWindow( GetDlgItem( hDlg, IDC_NONEXCLUSIVE ), TRUE );
  234.         EnableWindow( GetDlgItem( hDlg, IDC_FOREGROUND   ), TRUE );
  235.         EnableWindow( GetDlgItem( hDlg, IDC_BACKGROUND   ), TRUE );
  236.         EnableWindow( GetDlgItem( hDlg, IDC_IMMEDIATE    ), TRUE );
  237.         EnableWindow( GetDlgItem( hDlg, IDC_BUFFERED     ), TRUE );
  238.  
  239.         if( !bExclusive && bForeground )
  240.             EnableWindow( GetDlgItem( hDlg, IDC_WINDOWSKEY ), TRUE );
  241.         else
  242.             EnableWindow( GetDlgItem( hDlg, IDC_WINDOWSKEY ), FALSE );
  243.     }
  244.  
  245.     // Figure what the user should expect based on the dialog choice
  246.     if( !bForeground && bExclusive )
  247.     {
  248.         _tcscpy( strExcepted, TEXT("For security reasons, background exclusive ") \
  249.                              TEXT("keyboard access is not allowed.\n\n") );
  250.     }
  251.     else
  252.     {
  253.         if( bForeground )
  254.         {
  255.             _tcscpy( strExcepted, TEXT("Foreground cooperative level means that the ") \
  256.                                  TEXT("application has access to data only when in the ") \
  257.                                  TEXT("foreground or, in other words, has the input focus. ") \
  258.                                  TEXT("If the application moves to the background, ") \
  259.                                  TEXT("the device is automatically unacquired, or made ") \
  260.                                  TEXT("unavailable.\n\n") );
  261.         }
  262.         else
  263.         {
  264.             _tcscpy( strExcepted, TEXT("Background cooperative level really means ") \
  265.                                  TEXT("foreground and background. A device with a ") \
  266.                                  TEXT("background cooperative level can be acquired ") \
  267.                                  TEXT("and used by an application at any time.\n\n") );
  268.         }
  269.  
  270.         if( bExclusive )
  271.         {
  272.             _tcscat( strExcepted, TEXT("Exclusive mode prevents other applications from ") \
  273.                                  TEXT("also acquiring the device exclusively. The fact ") \
  274.                                  TEXT("that your application is using a device at the ") \
  275.                                  TEXT("exclusive level does not mean that other ") \
  276.                                  TEXT("applications cannot get data from the device. ") \
  277.                                  TEXT("When an application has exclusive access to the ") \
  278.                                  TEXT("keyboard, DirectInput suppresses all keyboard ") \
  279.                                  TEXT("messages including the Windows key except ") \
  280.                                  TEXT("CTRL+ALT+DEL and ALT+TAB\n\n") );
  281.         }
  282.         else
  283.         {
  284.             _tcscat( strExcepted, TEXT("Nonexclusive mode means that other applications ") \
  285.                                  TEXT("can acquire device in exclusive or nonexclusive mode. ") );
  286.  
  287.             if( bDisableWindowsKey )
  288.             {
  289.                 _tcscat( strExcepted, TEXT("The Windows key will also be disabled so that ") \
  290.                                      TEXT("users cannot inadvertently break out of the ") \
  291.                                      TEXT("application. ") );
  292.             }
  293.  
  294.             _tcscat( strExcepted, TEXT("\n\n") );
  295.         }
  296.  
  297.         if( bImmediate )
  298.         {
  299.             _tcscat( strExcepted, TEXT("Immediate data is a snapshot of the current ") \
  300.                                  TEXT("state of a device. It provides no data about ") \
  301.                                  TEXT("what has happened with the device since the ") \
  302.                                  TEXT("last call, apart from implicit information that ") \
  303.                                  TEXT("you can derive by comparing the current state with ") \
  304.                                  TEXT("the last one. Events in between calls are lost.\n\n") );
  305.         }
  306.         else
  307.         {
  308.             _tcscat( strExcepted, TEXT("Buffered data is a record of events that are stored ") \
  309.                                  TEXT("until an application retrieves them. With buffered ") \
  310.                                  TEXT("data, events are stored until you are ready to deal ") \
  311.                                  TEXT("with them. If the buffer overflows, new data is lost.\n\n") );                             
  312.         }
  313.  
  314.         _tcscat( strExcepted, TEXT("The sample will read the keyboard 12 times a second. ") \
  315.                              TEXT("Typically an application would poll the keyboard ") \
  316.                              TEXT("much faster than this, but this slow rate is simply ") \
  317.                              TEXT("for the purposes of demonstration.") );
  318.     }
  319.  
  320.     // Tell the user what to expect
  321.     SetDlgItemText( hDlg, IDC_BEHAVIOR, strExcepted );
  322. }
  323.  
  324.  
  325.  
  326.  
  327. //-----------------------------------------------------------------------------
  328. // Name: OnCreateDevice()
  329. // Desc: Setups a the keyboard device using the flags from the dialog.
  330. //-----------------------------------------------------------------------------
  331. HRESULT OnCreateDevice( HWND hDlg )
  332. {
  333.     HRESULT hr;
  334.     BOOL    bExclusive;
  335.     BOOL    bForeground;
  336.     BOOL    bImmediate;
  337.     BOOL    bDisableWindowsKey;
  338.     DWORD   dwCoopFlags;
  339. #ifdef _WIN64
  340.     HINSTANCE hInst = (HINSTANCE) GetWindowLongPtr( hDlg, GWLP_HINSTANCE );
  341. #else
  342.     HINSTANCE hInst = (HINSTANCE) GetWindowLong( hDlg, GWL_HINSTANCE );
  343. #endif
  344.  
  345.     // Cleanup any previous call first
  346.     KillTimer( hDlg, 0 );    
  347.     FreeDirectInput();
  348.  
  349.     // Detrimine where the buffer would like to be allocated 
  350.     bExclusive         = ( IsDlgButtonChecked( hDlg, IDC_EXCLUSIVE  ) == BST_CHECKED );
  351.     bForeground        = ( IsDlgButtonChecked( hDlg, IDC_FOREGROUND ) == BST_CHECKED );
  352.     bImmediate         = ( IsDlgButtonChecked( hDlg, IDC_IMMEDIATE  ) == BST_CHECKED );
  353.     bDisableWindowsKey = ( IsDlgButtonChecked( hDlg, IDC_WINDOWSKEY ) == BST_CHECKED );
  354.  
  355.     if( bExclusive )
  356.         dwCoopFlags = DISCL_EXCLUSIVE;
  357.     else
  358.         dwCoopFlags = DISCL_NONEXCLUSIVE;
  359.  
  360.     if( bForeground )
  361.         dwCoopFlags |= DISCL_FOREGROUND;
  362.     else
  363.         dwCoopFlags |= DISCL_BACKGROUND;
  364.  
  365.     // Disabling the windows key is only allowed only if we are in foreground nonexclusive
  366.     if( bDisableWindowsKey && !bExclusive && bForeground )
  367.         dwCoopFlags |= DISCL_NOWINKEY;
  368.  
  369.     // Create a DInput object
  370.     if( FAILED( hr = DirectInput8Create( GetModuleHandle(NULL), DIRECTINPUT_VERSION, 
  371.                                          IID_IDirectInput8, (VOID**)&g_pDI, NULL ) ) )
  372.         return hr;
  373.     
  374.     // Obtain an interface to the system keyboard device.
  375.     if( FAILED( hr = g_pDI->CreateDevice( GUID_SysKeyboard, &g_pKeyboard, NULL ) ) )
  376.         return hr;
  377.     
  378.     // Set the data format to "keyboard format" - a predefined data format 
  379.     //
  380.     // A data format specifies which controls on a device we
  381.     // are interested in, and how they should be reported.
  382.     //
  383.     // This tells DirectInput that we will be passing an array
  384.     // of 256 bytes to IDirectInputDevice::GetDeviceState.
  385.     if( FAILED( hr = g_pKeyboard->SetDataFormat( &c_dfDIKeyboard ) ) )
  386.         return hr;
  387.     
  388.     // Set the cooperativity level to let DirectInput know how
  389.     // this device should interact with the system and with other
  390.     // DirectInput applications.
  391.     hr = g_pKeyboard->SetCooperativeLevel( hDlg, dwCoopFlags );
  392.     if( hr == DIERR_UNSUPPORTED && !bForeground && bExclusive )
  393.     {
  394.         FreeDirectInput();
  395.         MessageBox( hDlg, _T("SetCooperativeLevel() returned DIERR_UNSUPPORTED.\n")
  396.                           _T("For security reasons, background exclusive keyboard\n")
  397.                           _T("access is not allowed."), _T("Keyboard"), MB_OK );
  398.         return S_OK;
  399.     }
  400.  
  401.     if( FAILED(hr) )
  402.         return hr;
  403.  
  404.     if( !bImmediate )
  405.     {
  406.         // IMPORTANT STEP TO USE BUFFERED DEVICE DATA!
  407.         //
  408.         // DirectInput uses unbuffered I/O (buffer size = 0) by default.
  409.         // If you want to read buffered data, you need to set a nonzero
  410.         // buffer size.
  411.         //
  412.         // Set the buffer size to DINPUT_BUFFERSIZE (defined above) elements.
  413.         //
  414.         // The buffer size is a DWORD property associated with the device.
  415.         DIPROPDWORD dipdw;
  416.  
  417.         dipdw.diph.dwSize       = sizeof(DIPROPDWORD);
  418.         dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
  419.         dipdw.diph.dwObj        = 0;
  420.         dipdw.diph.dwHow        = DIPH_DEVICE;
  421.         dipdw.dwData            = SAMPLE_BUFFER_SIZE; // Arbitary buffer size
  422.  
  423.         if( FAILED( hr = g_pKeyboard->SetProperty( DIPROP_BUFFERSIZE, &dipdw.diph ) ) )
  424.             return hr;
  425.     }
  426.  
  427.     // Acquire the newly created device
  428.     g_pKeyboard->Acquire();
  429.  
  430.     // Set a timer to go off 12 times a second, to read input
  431.     // Note: Typically an application would poll the keyboard
  432.     //       much faster than this, but this slow rate is simply 
  433.     //       for the purposes of demonstration
  434.     SetTimer( hDlg, 0, 1000 / 12, NULL );
  435.  
  436.     return S_OK;
  437. }
  438.  
  439.  
  440.  
  441.  
  442. //-----------------------------------------------------------------------------
  443. // Name: ReadImmediateData()
  444. // Desc: Read the input device's state when in immediate mode and display it.
  445. //-----------------------------------------------------------------------------
  446. HRESULT ReadImmediateData( HWND hDlg )
  447. {
  448.     HRESULT hr;
  449.     TCHAR   strNewText[256*5 + 1] = TEXT("");
  450.     TCHAR   strElement[10];    
  451.     BYTE    diks[256];   // DirectInput keyboard state buffer 
  452.     int     i;
  453.  
  454.     if( NULL == g_pKeyboard ) 
  455.         return S_OK;
  456.     
  457.     // Get the input's device state, and put the state in dims
  458.     ZeroMemory( &diks, sizeof(diks) );
  459.     hr = g_pKeyboard->GetDeviceState( sizeof(diks), &diks );
  460.     if( FAILED(hr) ) 
  461.     {
  462.         // DirectInput may be telling us that the input stream has been
  463.         // interrupted.  We aren't tracking any state between polls, so
  464.         // we don't have any special reset that needs to be done.
  465.         // We just re-acquire and try again.
  466.         
  467.         // If input is lost then acquire and keep trying 
  468.         hr = g_pKeyboard->Acquire();
  469.         while( hr == DIERR_INPUTLOST ) 
  470.             hr = g_pKeyboard->Acquire();
  471.  
  472.         // Update the dialog text 
  473.         if( hr == DIERR_OTHERAPPHASPRIO || hr == DIERR_NOTACQUIRED ) 
  474.             SetDlgItemText( hDlg, IDC_DATA, TEXT("Unacquired") );
  475.  
  476.         // hr may be DIERR_OTHERAPPHASPRIO or other errors.  This
  477.         // may occur when the app is minimized or in the process of 
  478.         // switching, so just try again later 
  479.         return S_OK; 
  480.     }
  481.     
  482.     // Make a string of the index values of the keys that are down
  483.     for( i = 0; i < 256; i++ ) 
  484.     {
  485.         if( diks[i] & 0x80 ) 
  486.         {
  487.             wsprintf( strElement, TEXT("0x%02x "), i );
  488.             _tcscat( strNewText, strElement );
  489.         }
  490.     }
  491.  
  492.     // Get the old text in the text box
  493.     TCHAR strOldText[128];
  494.     GetDlgItemText( hDlg, IDC_DATA, strOldText, 127 );
  495.     
  496.     // If nothing changed then don't repaint - avoid flicker
  497.     if( 0 != lstrcmp( strOldText, strNewText ) ) 
  498.         SetDlgItemText( hDlg, IDC_DATA, strNewText );
  499.     
  500.     return S_OK;
  501. }
  502.  
  503.  
  504.  
  505.  
  506. //-----------------------------------------------------------------------------
  507. // Name: ReadBufferedData()
  508. // Desc: Read the input device's state when in buffered mode and display it.
  509. //-----------------------------------------------------------------------------
  510. HRESULT ReadBufferedData( HWND hDlg )
  511. {
  512.     TCHAR              strNewText[256*5 + 1] = TEXT("");
  513.     TCHAR              strLetter[10];    
  514.     DIDEVICEOBJECTDATA didod[ SAMPLE_BUFFER_SIZE ];  // Receives buffered data 
  515.     DWORD              dwElements;
  516.     DWORD              i;
  517.     HRESULT            hr;
  518.  
  519.     if( NULL == g_pKeyboard ) 
  520.         return S_OK;
  521.     
  522.     dwElements = SAMPLE_BUFFER_SIZE;
  523.     hr = g_pKeyboard->GetDeviceData( sizeof(DIDEVICEOBJECTDATA),
  524.                                      didod, &dwElements, 0 );
  525.     if( hr != DI_OK ) 
  526.     {
  527.         // We got an error or we got DI_BUFFEROVERFLOW.
  528.         //
  529.         // Either way, it means that continuous contact with the
  530.         // device has been lost, either due to an external
  531.         // interruption, or because the buffer overflowed
  532.         // and some events were lost.
  533.         //
  534.         // Consequently, if a button was pressed at the time
  535.         // the buffer overflowed or the connection was broken,
  536.         // the corresponding "up" message might have been lost.
  537.         //
  538.         // But since our simple sample doesn't actually have
  539.         // any state associated with button up or down events,
  540.         // there is no state to reset.  (In a real game, ignoring
  541.         // the buffer overflow would result in the game thinking
  542.         // a key was held down when in fact it isn't; it's just
  543.         // that the "up" event got lost because the buffer
  544.         // overflowed.)
  545.         //
  546.         // If we want to be cleverer, we could do a
  547.         // GetDeviceState() and compare the current state
  548.         // against the state we think the device is in,
  549.         // and process all the states that are currently
  550.         // different from our private state.
  551.         hr = g_pKeyboard->Acquire();
  552.         while( hr == DIERR_INPUTLOST ) 
  553.             hr = g_pKeyboard->Acquire();
  554.  
  555.         // Update the dialog text 
  556.         if( hr == DIERR_OTHERAPPHASPRIO || 
  557.             hr == DIERR_NOTACQUIRED ) 
  558.             SetDlgItemText( hDlg, IDC_DATA, TEXT("Unacquired") );
  559.  
  560.         // hr may be DIERR_OTHERAPPHASPRIO or other errors.  This
  561.         // may occur when the app is minimized or in the process of 
  562.         // switching, so just try again later 
  563.         return S_OK; 
  564.     }
  565.  
  566.     if( FAILED(hr) )  
  567.         return hr;
  568.  
  569.     // Study each of the buffer elements and process them.
  570.     //
  571.     // Since we really don't do anything, our "processing"
  572.     // consists merely of squirting the name into our
  573.     // local buffer.
  574.     for( i = 0; i < dwElements; i++ ) 
  575.     {
  576.         // this will display then scan code of the key
  577.         // plus a 'D' - meaning the key was pressed 
  578.         //   or a 'U' - meaning the key was released
  579.         wsprintf( strLetter, TEXT("0x%02x%s "), didod[ i ].dwOfs,
  580.                                          (didod[ i ].dwData & 0x80) ? TEXT("D") : TEXT("U"));
  581.         _tcscat( strNewText, strLetter );
  582.     }
  583.  
  584.     // Get the old text in the text box
  585.     TCHAR strOldText[128];
  586.     GetDlgItemText( hDlg, IDC_DATA, strOldText, 127 );
  587.  
  588.     // If nothing changed then don't repaint - avoid flicker
  589.     if( 0 != lstrcmp( strOldText, strNewText ) ) 
  590.         SetDlgItemText( hDlg, IDC_DATA, strNewText );    
  591.  
  592.     return S_OK;
  593. }
  594.  
  595.  
  596.  
  597.  
  598. //-----------------------------------------------------------------------------
  599. // Name: FreeDirectInput()
  600. // Desc: Initialize the DirectInput variables.
  601. //-----------------------------------------------------------------------------
  602. VOID FreeDirectInput()
  603. {
  604.     // Unacquire the device one last time just in case 
  605.     // the app tried to exit while the device is still acquired.
  606.     if( g_pKeyboard ) 
  607.         g_pKeyboard->Unacquire();
  608.     
  609.     // Release any DirectInput objects.
  610.     SAFE_RELEASE( g_pKeyboard );
  611.     SAFE_RELEASE( g_pDI );
  612. }
  613.  
  614.  
  615.  
  616.  
  617.  
  618.  
  619.